package ru.spb.osll.myfit.client.widget;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;

import ru.spb.osll.myfit.common.PageElementType;
import ru.spb.osll.myfit.common.PageExecutingResult;
import ru.spb.osll.myfit.common.ProgressCounts;
import ru.spb.osll.myfit.common.Table;

import com.google.gwt.user.client.Timer;

public class PageExecutingListenerImpl implements PageExecutingListener {
  
  ArrayList<LinkedList<Integer>> indexes = new ArrayList<LinkedList<Integer>>();
  private Timer m_timer;
  private int executedTable = 0;
  private PageWidget rootPageWidget;
  private ProgressCounts m_counts = new ProgressCounts();
  private boolean m_finished=false;

  public PageExecutingListenerImpl(PageWidget pageWidget) {
    LinkedList<Integer> list = new LinkedList<Integer>();
    rootPageWidget = pageWidget;
    indexTables(list, rootPageWidget);
  }
  
  public void setCounts(ProgressCounts counts) {
    m_counts = counts;
  }
  
  public ProgressCounts getCounts () {
    return m_counts;
  }
  
  public boolean getFinished() {
    return m_finished;
  }

  @Override
  public void finish() {
    executedTable = 0;
    m_timer = null;
  }

  private void indexTables(List<Integer> prevIndexes, PageWidget pageWidget) {
    int size = pageWidget.getWidgetCount();

    for (int i = 0; i < size; i++) {
      PageElementWidget widget = pageWidget.getPageElementWidget(i);
      PageElementType type = widget.getType();
      switch (type) {
      case TABLE:
        LinkedList<Integer> newList = new LinkedList<Integer>(prevIndexes);
        newList.add(i);
        indexes.add(newList);
        break;
      case INCLUDE:
        LinkedList<Integer> list = new LinkedList<Integer>(prevIndexes);
        list.add(i);
        indexTables(list, ((IncludeWidget) widget).getPageWidget());
        break;
      default:
        break;
      }
    }
  }

  @Override
  public void processPageExecutingResult(PageExecutingResult result) {
    
    int size = result.getExecutedTables().size();
    if (size > executedTable) {
      List<Table> tables = result.getExecutedTables();
      for (int i = executedTable; i < size; i++) {                
        m_counts = result.getCounts();
        if ((result.getState() == PageExecutingResult.PageExecutingState.FINISH) || (result.getState() == PageExecutingResult.PageExecutingState.FAIL)) {m_finished = true;}
        insertTable(i, tables.get(i));
      }
      executedTable = size;
    }
  }

  private void insertTable(int index, Table table) {
    Queue<Integer> queue = indexes.get(index);
    PageWidget pageWidget = rootPageWidget;
    while (queue.size() > 1) {
      int position = queue.poll();
      PageElementWidget includeWidget = pageWidget.getElementWidget(position);
      pageWidget = ((IncludeWidget) includeWidget).getPageWidget();
    }

    if (queue.size() == 1) {
      int position = queue.poll();
      if (table != null) {
        pageWidget.removeWidget(position);
        pageWidget.addPageElementWidget(table, position);
      }
    }
  }

  @Override
  public void setTimer(Timer timer) {
    m_timer = timer;
  }

  @Override
  public void stopTimer() {
    m_timer.cancel();
  }

}
